package dao;

import java.util.*;
import javax.persistence.*;
import java.lang.reflect.ParameterizedType;


public class GenericDao<T> implements Dao<T>{
	
	protected static EntityManager manager;


	public GenericDao() {
		manager = getManager();	
	}
	
	protected static EntityManager getManager() {
		if (manager == null) {
			EntityManagerFactory factory = Persistence.createEntityManagerFactory("industria");
			manager = factory.createEntityManager();
		}
		return manager;		
	}

	public void persist(T obj) {
		begin();
		getManager().persist(obj);
		getManager().flush();
		commit();
	}

	public void remove(T obj) {
		begin();
			getManager().remove(obj);
			getManager().flush();
		commit();
	}

	@SuppressWarnings("unchecked")
	public T find(Object key) {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		T find = (T) getManager().find(type, key);
		return find;
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		
		Query q = manager.createQuery("SELECT o FROM "+type.getSimpleName()+" o");
		
		return (List<T>)q.getResultList();
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll(String by, String order) {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		
		Query q = manager.createQuery("SELECT o FROM "+type.getSimpleName()+" o ORDER BY o."+by+" "+order);
		
		return (List<T>)q.getResultList();
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll(String by, String order, String where) {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		
		Query q = manager.createQuery("SELECT o FROM "+type.getSimpleName()+" o WHERE "+where+"  ORDER BY o."+by+" "+order);
		
		return (List<T>)q.getResultList();
	}
	
	public void begin() {
		if (!getManager().getTransaction().isActive())
			getManager().getTransaction().begin();
	}

	public void commit() {
		if (getManager().getTransaction().isActive())
			getManager().getTransaction().commit();	
	}

	public void merge(T obj) {
		begin();
		getManager().merge(obj);
		getManager().flush();
		commit();
	}



}
